package packageDataAccess;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import javax.sql.DataSource;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NamingException;
import packageException.*;
import packageModel.Composition;

/**
 *
 * @author Lionel & Julien
 * 
 */
public class CompositionSyllathequeData {
    /**
     * Recherche la dernière composition afin de pouvoir calculé un nouvel id !
     * 
     * @return numCde
     * @throws CompositionException
     * @throws DataException  
     */
    public int lastNumCompo() throws 
            CompositionException,
            DataException {
        int lastNumCompo = -1;
        try {
            // Connexion à la base de données
            Context ctx = new InitialContext(); 
            DataSource source = (DataSource) ctx.lookup("jdbc/Syllatheque"); 
            Connection connexion = source.getConnection();
            
            // SQL
            String requeteSql = "SELECT MAX(compoId) "
                    + "FROM Composition";

            // Traitement
            PreparedStatement prepStat = connexion.prepareStatement(requeteSql);

            ResultSet donnees = prepStat.executeQuery();
            donnees.next();
            
            lastNumCompo = donnees.getInt(1);
            lastNumCompo++;
            
            // Fermeture de la connexion
            connexion.close();
        } catch(SQLException e) {
            // ERREUR
            throw new CompositionException(e.getMessage());
        }
        catch(NamingException e) {
            // ERREUR
            throw new DataException(e.getMessage());
        }
        return lastNumCompo;
    }
    
    
    /**
     * Insertion d'une nouvelle composition !
     * 
     * @param numCde
     * @param syllabusId
     * @param quantite
     * @param prix
     * @return Composition
     * @throws CompositionException
     * @throws CommandeException
     * @throws SyllabusException
     * @throws DataException  
     */
    public Composition insertComposition(int numCde, int syllabusId, int quantite, double prix) throws 
            CompositionException, 
            CommandeException, 
            SyllabusException,
            DataException {
        Composition compo = null;
        try {
            // Connexion à la base de données
            Context ctx = new InitialContext(); 
            DataSource source = (DataSource) ctx.lookup("jdbc/Syllatheque"); 
            Connection connexion = source.getConnection();
            
            SyllabusSyllathequeData ssdb = new SyllabusSyllathequeData();
            CommandeSyllathequeData csdb = new CommandeSyllathequeData();
            int lastNumCompo = this.lastNumCompo();
            
            // SQL
            String requeteSql = "INSERT INTO "
                    + "Composition(compoId, numCdeCompo, syllabusId, quantite, prix) "
                    + "VALUES(?, ?, ?, ?, ?)";
            
            // Traitement
            PreparedStatement prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setInt(1, lastNumCompo);
            prepStat.setInt(2, numCde);
            prepStat.setInt(3, syllabusId);
            prepStat.setInt(4, quantite);
            prepStat.setDouble(5, prix);
            
            compo = new Composition(
                        lastNumCompo,
                        csdb.getCommandeByCde(numCde), 
                        ssdb.getSyllabusById(syllabusId), 
                        quantite, 
                        prix
                    );
            
            prepStat.executeUpdate();
            
            // Fermeture de la connexion
            connexion.close();
        }
        catch(SQLException e) {
            // ERREUR
            throw new CompositionException(e.getMessage());
        }
        catch(NamingException e) {
            // ERREUR
            throw new DataException(e.getMessage());
        }
        return compo;
    }

    
    
    /**
     * Récupère toutes les compositions concernant la commande (numCde)
     * 
     * @param numCde
     * @return ArrayList<Composition>
     * @throws CompositionException
     * @throws CommandeException
     * @throws SyllabusException
     * @throws DataException  
     */
    public ArrayList<Composition> getCompositionByCde(int numCde) throws 
            CompositionException, 
            CommandeException, 
            SyllabusException,
            DataException {
        ArrayList<Composition> tabCompo = new ArrayList<Composition>();
        Composition compo = null;
        try {
            // Connexion à la base de données
            Context ctx = new InitialContext(); 
            DataSource source = (DataSource) ctx.lookup("jdbc/Syllatheque"); 
            Connection connexion = source.getConnection();
            
            SyllabusSyllathequeData ssdb = new SyllabusSyllathequeData();
            CommandeSyllathequeData csdb = new CommandeSyllathequeData();
            
            // SQL
            String requeteSql = "SELECT * "
                    + "FROM Composition "
                    + "WHERE numCdeCompo = ?";

            // Traitement
            PreparedStatement prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setInt(1, numCde);

            ResultSet donnees = prepStat.executeQuery();
            while(donnees.next()) {
                compo= new Composition(
                        donnees.getInt("compoId"),
                        csdb.getCommandeByCde(donnees.getInt("numCdeCompo")), 
                        ssdb.getSyllabusById(donnees.getInt("syllabusId")), 
                        donnees.getInt("quantite"), 
                        donnees.getDouble("prix")
                      );
                tabCompo.add(compo);
            }
            
            // Fermeture de la connexion
            connexion.close();
        }
        catch(SQLException e) {
            // ERREUR
            throw new CommandeException(e.getMessage());
        }
        catch(NamingException e) {
            // ERREUR
            throw new DataException(e.getMessage());
        }
        return tabCompo;
    }

    
    /**
     * L'utilisateur (pseudo) a-t-il déjà une composition concernant le syllabusId ?
     * 
     * @param syllabusId
     * @param pseudo
     * @return true OR false
     * @throws CompositionException
     * @throws CommandeException
     * @throws DataException  
     */
    public boolean existComposition(int syllabusId, String pseudo) throws 
            CompositionException, 
            CommandeException,
            DataException {
        Boolean isExist = false;
        try {
            // Connexion à la base de données
            Context ctx = new InitialContext(); 
            DataSource source = (DataSource) ctx.lookup("jdbc/Syllatheque"); 
            Connection connexion = source.getConnection();
            
            // SQL
            String requeteSql = "SELECT COUNT(*) as nb "
                    + "FROM Composition "
                    + "WHERE numCdeCompo = (SELECT numCde "
                    + "FROM Commande "
                    + "WHERE pseudo = ? "
                    + "AND isCloturee = 0) "
                    + "AND syllabusId = ?";
                        
            // Traitement
            PreparedStatement prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setString(1, pseudo);
            prepStat.setInt(2, syllabusId);
            
            ResultSet donnees = prepStat.executeQuery();
            donnees.next();
            
            int nb = donnees.getInt("nb");
            if(nb != 0)
                isExist = true;
            
            // Fermeture de la connexion
            connexion.close();
        }
        catch(SQLException e) {
            // ERREUR
            throw new CompositionException(e.getMessage());
        }
        catch(NamingException e) {
            // ERREUR
            throw new DataException(e.getMessage());
        }
        return isExist;
    }

    
    /**
     * Modification de la quantité de la composition
     * 
     * @param syllabusId
     * @param pseudo
     * @param quantite
     * @param param
     * @return Composition
     * @throws CompositionException
     * @throws CommandeException
     * @throws SyllabusException
     * @throws DataException  
     */
    public Composition modifyQuantity(int syllabusId, String pseudo, int quantite, String param) throws 
            CompositionException, 
            CommandeException, 
            SyllabusException,
            DataException {
        Composition compo = null;
        try {
            // Connexion à la base de données
            Context ctx = new InitialContext(); 
            DataSource source = (DataSource) ctx.lookup("jdbc/Syllatheque"); 
            Connection connexion = source.getConnection();
            
            SyllabusSyllathequeData ssdb = new SyllabusSyllathequeData();
            CommandeSyllathequeData csdb = new CommandeSyllathequeData();
            
            // SQL
            String requeteSql = "SELECT * FROM composition "
                    + "WHERE numCdeCompo = "
                    + "(SELECT numCDE FROM Commande WHERE pseudo = ? AND isCloturee = 0) "
                    + "AND syllabusId = ?";
            
            // Traitement
            // On récupére la ligne dans la base de données afin de pouvoir l'éditer par la suite
            PreparedStatement prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setString(1, pseudo);
            prepStat.setInt(2, syllabusId);
            
            ResultSet donnees = prepStat.executeQuery();
            donnees.next();
            
            // On regarde si l'argument 'param' est add ou egal afin de savoir quoi faire avec les quantités.
            // Si c'est add, on ajoute à la quantité existante
            // Si c'est egal, on remplace par la nouvelle quantité
            int newQuantite = 0;
            if(param.equals("add"))
                newQuantite = donnees.getInt("quantite") + quantite;
            else
                newQuantite = quantite;

            // Récupération de la commande. On y met également la quantité modifiée
            compo = new Composition(
                        donnees.getInt("compoId"),
                        csdb.getCommandeByCde(donnees.getInt("numCdeCompo")), 
                        ssdb.getSyllabusById(donnees.getInt("syllabusId")), 
                        newQuantite, 
                        donnees.getDouble("prix")
                      );
            
            // SQL
            requeteSql = "UPDATE Composition "
                    + "SET quantite = ? "
                    + "WHERE numCdeCompo = (SELECT numCDE FROM Commande WHERE pseudo = ? AND isCloturee = 0) "
                    + "AND syllabusId = ?";
            
            // Traitement
            prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setInt(1, compo.getQuantite());
            prepStat.setString(2, pseudo);
            prepStat.setInt(3, syllabusId);

            prepStat.executeUpdate();

            // Fermeture de la connexion
            connexion.close();
        }
        catch(SQLException e) {
            // ERREUR
            throw new CompositionException(e.getMessage());
        }
        catch(NamingException e) {
            // ERREUR
            throw new DataException(e.getMessage());
        }
        return compo;
    }

    
    
    
    /**
     * Modification du prix de la composition
     * 
     * @param syllabusId
     * @param pseudo
     * @param prix
     * @return Composition
     * @throws CompositionException
     * @throws CommandeException
     * @throws SyllabusException
     * @throws DataException  
     */
    public Composition modifyPrix(int syllabusId, String pseudo, double prix) throws 
            CompositionException,
            CommandeException, 
            SyllabusException,
            DataException {
        Composition compo = null;
        try {
            // Connexion à la base de données
            Context ctx = new InitialContext(); 
            DataSource source = (DataSource) ctx.lookup("jdbc/Syllatheque"); 
            Connection connexion = source.getConnection();
            
            SyllabusSyllathequeData ssdb = new SyllabusSyllathequeData();
            CommandeSyllathequeData csdb = new CommandeSyllathequeData();
            
            // SQL
            String requeteSql = "UPDATE Composition "
                    + "SET prix = ? "
                    + "WHERE numCdeCompo = (SELECT numCDE FROM Commande WHERE pseudo = ? AND isCloturee = 0) "
                    + "AND syllabusId = ?";
            
            // Traitement
            PreparedStatement prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setDouble(1, prix);
            prepStat.setString(2, pseudo);
            prepStat.setInt(3, syllabusId);
            
            prepStat.executeUpdate();
            
            // SQL
            requeteSql = "SELECT * "
                    + "FROM Composition "
                    + "WHERE numCdeCompo = (SELECT numCDE FROM Commande WHERE pseudo = ? AND isCloturee = 0) "
                    + "AND syllabusId = ?";
            
            // Traitement
            prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setString(1, pseudo);
            prepStat.setInt(2, syllabusId);
            
            ResultSet donnees = prepStat.executeQuery();
            donnees.next();

            compo = new Composition(
                        donnees.getInt("compoId"),
                        csdb.getCommandeByCde(donnees.getInt("numCdeCompo")), 
                        ssdb.getSyllabusById(donnees.getInt("syllabusId")), 
                        donnees.getInt("quantite"), 
                        donnees.getDouble("prix")
                      );

            // Fermeture de la connexion
            connexion.close();
        }
        catch(SQLException e) {
            // ERREUR
            throw new CompositionException(e.getMessage());
        }
        catch(NamingException e) {
            // ERREUR
            throw new DataException(e.getMessage());
        }
        return compo;
    }
    
    
    /**
     * Suppression de la composition dont l'id est passé en paramètre
     * 
     * @param compoId
     * @throws CompositionException
     * @throws DataException  
     */
    public void deleteCompo(int compoId) throws 
            CompositionException,
            DataException {
        try {
            // Connexion à la base de données
            Context ctx = new InitialContext(); 
            DataSource source = (DataSource) ctx.lookup("jdbc/Syllatheque"); 
            Connection connexion = source.getConnection();
            
            // SQL
            String requeteSql = "DELETE FROM Composition "
                    + "WHERE compoId = ?";
            
            // Traitement
            PreparedStatement prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setInt(1, compoId);
            
            prepStat.executeUpdate();
            
            // Fermeture de la connexion
            connexion.close();
        }
        catch(SQLException e) {
            // ERREUR
            throw new CompositionException(e.getMessage());
        }
        catch(NamingException e) {
            // ERREUR
            throw new DataException(e.getMessage());
        }
    }

    /**
     * Clôturer la commande de l'utilisateur passé en paramètre
     * 
     * @param pseudo
     * @throws CommandeException
     * @throws DataException  
     */
    public void cloturerCommande(String pseudo) throws 
            CommandeException,
            DataException {
        try {
            // Connexion à la base de données
            Context ctx = new InitialContext(); 
            DataSource source = (DataSource) ctx.lookup("jdbc/Syllatheque"); 
            Connection connexion = source.getConnection();
            
            // SQL
            String requeteSql = "UPDATE Commande SET dateCloture = ?, isCloturee = 1 "
                    + "WHERE pseudo = ? AND isCloturee = 0";
            
            // Traitement
            GregorianCalendar auj = new GregorianCalendar();
            java.sql.Date dateClot = new java.sql.Date(auj.getTimeInMillis());
            
            PreparedStatement prepStat = connexion.prepareStatement(requeteSql);
            prepStat.setDate(1, dateClot);
            prepStat.setString(2, pseudo);
            
            prepStat.executeUpdate();
            
            // Fermeture de la connexion
            connexion.close();
        }
        catch(SQLException e) {
            // ERREUR
            throw new CommandeException(e.getMessage());
        }
        catch(NamingException e) {
            // ERREUR
            throw new DataException(e.getMessage());
        }
    }
}
